home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS 1.31 / antlr / build.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-10  |  17.1 KB  |  713 lines  |  [TEXT/MPS ]

  1. /*
  2.  * build.c -- functions associated with building syntax diagrams.
  3.  *
  4.  * $Id: build.c,v 1.10 1994/12/31 21:02:55 parrt Exp parrt $
  5.  * $Revision: 1.10 $
  6.  *
  7.  * SOFTWARE RIGHTS
  8.  *
  9.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  10.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  11.  * company may do whatever they wish with source code distributed with
  12.  * PCCTS or the code generated by PCCTS, including the incorporation of
  13.  * PCCTS, or its output, into commerical software.
  14.  * 
  15.  * We encourage users to develop software with PCCTS.  However, we do ask
  16.  * that credit is given to us for developing PCCTS.  By "credit",
  17.  * we mean that if you incorporate our source code into one of your
  18.  * programs (commercial product, research project, or otherwise) that you
  19.  * acknowledge this fact somewhere in the documentation, research report,
  20.  * etc...  If you like PCCTS and have developed a nice tool with the
  21.  * output, please mention that you developed it using PCCTS.  In
  22.  * addition, we ask that this header remain intact in our source code.
  23.  * As long as these guidelines are kept, we expect to continue enhancing
  24.  * this system and expect to make other tools available as they are
  25.  * completed.
  26.  *
  27.  * ANTLR 1.31
  28.  * Terence Parr
  29.  * Parr Research Corporation
  30.  * with Purdue University and AHPCRC, University of Minnesota
  31.  * 1989-1995
  32.  */
  33. #include <stdio.h>
  34. #ifdef __cplusplus
  35. #ifndef __STDC__
  36. #define __STDC__
  37. #endif
  38. #endif
  39. #include "set.h"
  40. #include "syn.h"
  41. #include "hash.h"
  42. #include "generic.h"
  43. #include "dlgdef.h"
  44.  
  45. #define SetBlk(g, t, approx) {                                       \
  46.             ((Junction *)g.left)->jtype = t;                    \
  47.             ((Junction *)g.left)->approx = approx;                \
  48.             ((Junction *)g.left)->end = (Junction *) g.right;    \
  49.             ((Junction *)g.right)->jtype = EndBlk;}
  50.  
  51. /* Add the parameter string 'parm' to the parms field of a block-type junction
  52.  * g.left points to the sentinel node on a block.  i.e. g.left->p1 points to
  53.  * the actual junction with its jtype == some block-type.
  54.  */
  55. void
  56. #ifdef __STDC__
  57. addParm( Node *p, char *parm )
  58. #else
  59. addParm( p, parm )
  60. Node *p;
  61. char *parm;
  62. #endif
  63. {
  64.     char *q = (char *) malloc( strlen(parm) + 1 );
  65.     require(p!=NULL, "addParm: NULL object\n");
  66.     require(q!=NULL, "addParm: unable to alloc parameter\n");
  67.  
  68.     strcpy(q, parm);
  69.     if ( p->ntype == nRuleRef )
  70.     {
  71.         ((RuleRefNode *)p)->parms = q;
  72.     }
  73.     else if ( p->ntype == nJunction )
  74.     {
  75.         ((Junction *)p)->parm = q;    /* only one parameter allowed on subrules */
  76.     }
  77.     else fatal_internal("addParm: invalid node for adding parm");
  78. }
  79.  
  80. /*
  81.  * Build an action node for the syntax diagram
  82.  *
  83.  * buildAction(ACTION) ::= --o-->ACTION-->o--
  84.  *
  85.  * Where o is a junction node.
  86.  */
  87. Graph
  88. #ifdef __STDC__
  89. buildAction( char *action, int file, int line, int is_predicate )
  90. #else
  91. buildAction( action, file, line, is_predicate )
  92. char *action;
  93. int file;
  94. int line;
  95. int is_predicate;
  96. #endif
  97. {
  98.     Junction *j1, *j2;
  99.     Graph g;
  100.     ActionNode *a;
  101.     require(action!=NULL, "buildAction: invalid action");
  102.     
  103.     j1 = newJunction();
  104.     j2 = newJunction();
  105.     a = newActionNode();
  106.     a->action = (char *) malloc( strlen(action)+1 );
  107.     require(a->action!=NULL, "buildAction: cannot alloc space for action\n");
  108.     strcpy(a->action, action);
  109.     j1->p1 = (Node *) a;
  110.     a->next = (Node *) j2;
  111.     a->is_predicate = is_predicate;
  112.     g.left = (Node *) j1; g.right = (Node *) j2;
  113.     a->file = file;
  114.     a->line = line;
  115.     return g;
  116. }
  117.  
  118. /*
  119.  * Build a token node for the syntax diagram
  120.  *
  121.  * buildToken(TOKEN) ::= --o-->TOKEN-->o--
  122.  *
  123.  * Where o is a junction node.
  124.  */
  125. Graph
  126. #ifdef __STDC__
  127. buildToken( char *text )
  128. #else
  129. buildToken( text )
  130. char *text;
  131. #endif
  132. {
  133.     Junction *j1, *j2;
  134.     Graph g;
  135.     TokNode *t;
  136.     require(text!=NULL, "buildToken: invalid token name");
  137.     
  138.     j1 = newJunction();
  139.     j2 = newJunction();
  140.     t = newTokNode();
  141.     t->altstart = CurAltStart;
  142.     if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );}
  143.     else {t->label=TRUE; t->token = addTname( text );}
  144.     j1->p1 = (Node *) t;
  145.     t->next = (Node *) j2;
  146.     g.left = (Node *) j1; g.right = (Node *) j2;
  147.     return g;
  148. }
  149.  
  150. /*
  151.  * Build a wild-card node for the syntax diagram
  152.  *
  153.  * buildToken(TOKEN) ::= --o-->'.'-->o--
  154.  *
  155.  * Where o is a junction node.
  156.  */
  157. Graph
  158. #ifdef __STDC__
  159. buildWildCard( char *text )
  160. #else
  161. buildWildCard( text )
  162. char *text;
  163. #endif
  164. {
  165.     Junction *j1, *j2;
  166.     Graph g;
  167.     TokNode *t;
  168.     TCnode *w;
  169.     TermEntry *p;
  170.     require(text!=NULL, "buildWildCard: invalid token name");
  171.     
  172.     j1 = newJunction();
  173.     j2 = newJunction();
  174.     t = newTokNode();
  175.  
  176.     /* If the ref a wild card, make a token class for it */
  177.     if ( Tnum(WildCardString) == 0 )
  178.     {
  179.         w = newTCnode;
  180.           w->tok = addTname( WildCardString );
  181.         set_orel(w->tok, &imag_tokens);
  182.         set_orel(w->tok, &tokclasses);
  183.         WildCardToken = w->tok;
  184.         require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL,
  185.                 "hash table mechanism is broken");
  186.         p->classname = 1;    /* entry is class name, not token */
  187.         p->tclass = w;        /* save ptr to this tclass def */
  188.         list_add(&tclasses, (char *)w);
  189.     }
  190.     else {
  191.         p=(TermEntry *)hash_get(Tname, WildCardString);
  192.         require( p!= NULL, "hash table mechanism is broken");
  193.         w = p->tclass;
  194.     }
  195.  
  196.     t->token = w->tok;
  197.     t->wild_card = 1;
  198.     t->tclass = w;
  199.  
  200.     t->altstart = CurAltStart;
  201.     j1->p1 = (Node *) t;
  202.     t->next = (Node *) j2;
  203.     g.left = (Node *) j1; g.right = (Node *) j2;
  204.     return g;
  205. }
  206.  
  207. void
  208. #ifdef __STDC__
  209. setUpperRange(TokNode *t, char *text)
  210. #else
  211. setUpperRange(t, text)
  212. TokNode *t;
  213. char *text;
  214. #endif
  215. {
  216.     require(t!=NULL, "setUpperRange: NULL token node");
  217.     require(text!=NULL, "setUpperRange: NULL token string");
  218.  
  219.     if ( *text == '"' ) {t->upper_range = addTexpr( text );}
  220.     else {t->upper_range = addTname( text );}
  221. }
  222.  
  223. /*
  224.  * Build a rule reference node of the syntax diagram
  225.  *
  226.  * buildRuleRef(RULE) ::= --o-->RULE-->o--
  227.  *
  228.  * Where o is a junction node.
  229.  *
  230.  * If rule 'text' has been defined already, don't alloc new space to store string.
  231.  * Set r->text to point to old copy in string table.
  232.  */
  233. Graph
  234. #ifdef __STDC__
  235. buildRuleRef( char *text )
  236. #else
  237. buildRuleRef( text )
  238. char *text;
  239. #endif
  240. {
  241.     Junction *j1, *j2;
  242.     Graph g;
  243.     RuleRefNode *r;
  244.     RuleEntry *p;
  245.     require(text!=NULL, "buildRuleRef: invalid rule name");
  246.     
  247.     j1 = newJunction();
  248.     j2 = newJunction();
  249.     r = newRNode();
  250.     r->altstart = CurAltStart;
  251.     r->assign = NULL;
  252.     if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str;
  253.     else r->text = mystrdup( text );
  254.     j1->p1  = (Node *) r;
  255.     r->next = (Node *) j2;
  256.     g.left = (Node *) j1; g.right = (Node *) j2;
  257.     return g;
  258. }
  259.  
  260. /*
  261.  * Or two subgraphs into one graph via:
  262.  *
  263.  * Or(G1, G2) ::= --o-G1-o--
  264.  *                  |    ^
  265.  *                    v    |
  266.  *                  o-G2-o
  267.  *
  268.  * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1.
  269.  * If, however, the G1 altnum is 0, make it 1 and then
  270.  * make G2 altnum = G1 altnum + 1.
  271.  */
  272. Graph
  273. #ifdef __STDC__
  274. Or( Graph g1, Graph g2 )
  275. #else
  276. Or( g1, g2 )
  277. Graph g1;
  278. Graph g2;
  279. #endif
  280. {
  281.     Graph g;
  282.     require(g1.left != NULL, "Or: invalid graph");
  283.     require(g2.left != NULL && g2.right != NULL, "Or: invalid graph");
  284.  
  285.     ((Junction *)g1.left)->p2 = g2.left;
  286.     ((Junction *)g2.right)->p1 = g1.right;
  287.     /* set altnums */
  288.     if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
  289.     ((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1;
  290.     g.left = g2.left;
  291.     g.right = g1.right;
  292.     return g;
  293. }
  294.  
  295. /*
  296.  * Catenate two subgraphs
  297.  *
  298.  * Cat(G1, G2) ::= --o-G1-o-->o-G2-o--
  299.  * Cat(NULL,G2)::= --o-G2-o--
  300.  * Cat(G1,NULL)::= --o-G1-o--
  301.  */
  302. Graph
  303. #ifdef __STDC__
  304. Cat( Graph g1, Graph g2 )
  305. #else
  306. Cat( g1, g2 )
  307. Graph g1;
  308. Graph g2;
  309. #endif
  310. {
  311.     Graph g;
  312.     
  313.     if ( g1.left == NULL && g1.right == NULL ) return g2;
  314.     if ( g2.left == NULL && g2.right == NULL ) return g1;
  315.     ((Junction *)g1.right)->p1 = g2.left;
  316.     g.left = g1.left;
  317.     g.right = g2.right;
  318.     return g;
  319. }
  320.  
  321. /*
  322.  * Make a subgraph an optional block
  323.  *
  324.  * makeOpt(G) ::= --o-->o-G-o-->o--
  325.  *                      |         ^
  326.  *                        v          |
  327.  *                        o-------o
  328.  *
  329.  * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found.
  330.  *
  331.  * The node on the far right is added so that every block owns its own
  332.  * EndBlk node.
  333.  */
  334. Graph
  335. #ifdef __STDC__
  336. makeOpt( Graph g1, int approx )
  337. #else
  338. makeOpt( g1, approx )
  339. Graph g1;
  340. int approx;
  341. #endif
  342. {
  343.     Junction *j1,*j2,*p;
  344.     Graph g;
  345.     require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph");
  346.  
  347.     j1 = newJunction();
  348.     j2 = newJunction();
  349.     ((Junction *)g1.right)->p1 = (Node *) j2;    /* add node to G at end */
  350.     g = emptyAlt();
  351.     if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
  352.     ((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1;
  353.     for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2)
  354.         {;}                                        /* find last alt */
  355.     p->p2 = g.left;                                /* add optional alternative */
  356.     ((Junction *)g.right)->p1 = (Node *)j2;        /* opt alt points to EndBlk */
  357.     g1.right = (Node *)j2;
  358.     SetBlk(g1, aOptBlk, approx);
  359.     j1->p1 = g1.left;                            /* add generic node in front */
  360.     g.left = (Node *) j1;
  361.     g.right = g1.right;
  362.  
  363.     return g;
  364. }
  365.  
  366. /*
  367.  * Make a graph into subblock
  368.  *
  369.  * makeBlk(G) ::= --o-->o-G-o-->o--
  370.  *
  371.  * The node on the far right is added so that every block owns its own
  372.  * EndBlk node.
  373.  */
  374. Graph
  375. #ifdef __STDC__
  376. makeBlk( Graph g1, int approx )
  377. #else
  378. makeBlk( g1, approx )
  379. Graph g1;
  380. int approx;
  381. #endif
  382. {
  383.     Junction *j,*j2;
  384.     Graph g;
  385.     require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph");
  386.  
  387.     j = newJunction();
  388.     j2 = newJunction();
  389.     ((Junction *)g1.right)->p1 = (Node *) j2;    /* add node to G at end */
  390.     g1.right = (Node *)j2;
  391.     SetBlk(g1, aSubBlk, approx);
  392.     j->p1 = g1.left;                            /* add node in front */
  393.     g.left = (Node *) j;
  394.     g.right = g1.right;
  395.  
  396.     return g;
  397. }
  398.  
  399. /*
  400.  * Make a subgraph into a loop (closure) block -- (...)*
  401.  *
  402.  * makeLoop(G) ::=       |---|
  403.  *                         v   |
  404.  *               --o-->o-->o-G-o-->o--
  405.  *                   |           ^
  406.  *                   v           |
  407.  *                     o-----------o
  408.  *
  409.  * After making loop, always place generic node out front.  It becomes
  410.  * the start of enclosing block.  The aLoopBlk is the target of the loop.
  411.  *
  412.  * Loop blks have TWO EndBlk nodes--the far right and the node that loops back
  413.  * to the aLoopBlk node.  Node with which we can branch past loop == aLoopBegin and
  414.  * one which is loop target == aLoopBlk.
  415.  * The branch-past (initial) aLoopBegin node has end
  416.  * pointing to the last EndBlk node.  The loop-target node has end==NULL.
  417.  *
  418.  * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node.
  419.  */
  420. Graph
  421. #ifdef __STDC__
  422. makeLoop( Graph g1, int approx )
  423. #else
  424. makeLoop( g1, approx )
  425. Graph g1;
  426. int approx;
  427. #endif
  428. {
  429.     Junction *back, *front, *begin;
  430.     Graph g;
  431.     require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph");
  432.  
  433.     back = newJunction();
  434.     front = newJunction();
  435.     begin = newJunction();
  436.     g = emptyAlt();
  437.     ((Junction *)g1.right)->p2 = g1.left;        /* add loop branch to G */
  438.     ((Junction *)g1.right)->p1 = (Node *) back;    /* add node to G at end */
  439.     ((Junction *)g1.right)->jtype = EndBlk;        /* mark 1st EndBlk node */
  440.     ((Junction *)g1.left)->jtype = aLoopBlk;    /* mark 2nd aLoopBlk node */
  441.     ((Junction *)g1.left)->end = (Junction *) g1.right;
  442.     ((Junction *)g1.left)->lock = makelocks();
  443.     ((Junction *)g1.left)->pred_lock = makelocks();
  444.     g1.right = (Node *) back;
  445.     begin->p1 = (Node *) g1.left;
  446.     g1.left = (Node *) begin;
  447.     begin->p2 = (Node *) g.left;                /* make bypass arc */
  448.     ((Junction *)g.right)->p1 = (Node *) back;
  449.     SetBlk(g1, aLoopBegin, approx);
  450.     front->p1 = g1.left;                        /* add node to front */
  451.     g1.left = (Node *) front;
  452.  
  453.     return g1;
  454. }
  455.  
  456. /*
  457.  * Make a subgraph into a plus block -- (...)+ -- 1 or more times
  458.  *
  459.  * makePlus(G) ::=     |---|
  460.  *                     v   |
  461.  *               --o-->o-G-o-->o--
  462.  *
  463.  * After making loop, always place generic node out front.  It becomes
  464.  * the start of enclosing block.  The aPlusBlk is the target of the loop.
  465.  *
  466.  * Plus blks have TWO EndBlk nodes--the far right and the node that loops back
  467.  * to the aPlusBlk node.
  468.  *
  469.  * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node.
  470.  */
  471. Graph
  472. #ifdef __STDC__
  473. makePlus( Graph g1, int approx )
  474. #else
  475. makePlus( g1, approx )
  476. Graph g1;
  477. int approx;
  478. #endif
  479. {
  480.     int has_empty_alt_already = 0;
  481.     Graph g;
  482.     Junction *j2, *j3, *first_alt;
  483.     Junction *last_alt, *p;
  484.     require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph");
  485.  
  486.     first_alt = (Junction *)g1.left;
  487.     j2 = newJunction();
  488.     j3 = newJunction();
  489.     if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
  490.     ((Junction *)g1.right)->p2 = g1.left;        /* add loop branch to G */
  491.     ((Junction *)g1.right)->p1 = (Node *) j2;    /* add node to G at end */
  492.     ((Junction *)g1.right)->jtype = EndBlk;        /* mark 1st EndBlk node */
  493.     g1.right = (Node *) j2;
  494.     SetBlk(g1, aPlusBlk, approx);
  495.     ((Junction *)g1.left)->lock = makelocks();
  496.     ((Junction *)g1.left)->pred_lock = makelocks();
  497.     j3->p1 = g1.left;                            /* add node to front */
  498.     g1.left = (Node *) j3;
  499.  
  500.     /* add an optional branch which is the "exit" branch of loop */
  501.     /* FIRST, check to ensure that there does not already exist
  502.      * an optional path.
  503.      */
  504.     /* find last alt */
  505.     for(p=first_alt; p!=NULL; p=(Junction *)p->p2)
  506.     {
  507.         if ( p->p1->ntype == nJunction &&
  508.              p->p1!=NULL &&
  509.              ((Junction *)p->p1)->jtype==Generic &&
  510.              ((Junction *)p->p1)->p1!=NULL &&
  511.              ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk )
  512.         {
  513.             has_empty_alt_already = 1;
  514.         }
  515.         last_alt = p;
  516.     }
  517.     if ( !has_empty_alt_already )
  518.     {
  519.         require(last_alt!=NULL, "last_alt==NULL; bad (..)+");
  520.         g = emptyAlt();
  521.         last_alt->p2 = g.left;
  522.         ((Junction *)g.right)->p1 = (Node *) j2;
  523.  
  524.         /* make sure lookahead computation ignores this alt for
  525.         * FIRST("(..)+"); but it's still used for computing the FIRST
  526.         * of each alternative.
  527.         */
  528.         ((Junction *)g.left)->ignore = 1;
  529.     }
  530.  
  531.     return g1;
  532. }
  533.  
  534. /*
  535.  * Return an optional path:  --o-->o--
  536.  */
  537. Graph
  538. #ifdef __STDC__
  539. emptyAlt( void )
  540. #else
  541. emptyAlt( )
  542. #endif
  543. {
  544.     Junction *j1, *j2;
  545.     Graph g;
  546.  
  547.     j1 = newJunction();
  548.     j2 = newJunction();
  549.     j1->p1 = (Node *) j2;
  550.     g.left = (Node *) j1;
  551.     g.right = (Node *) j2;
  552.     
  553.     return g;
  554. }
  555.  
  556. /* N o d e  A l l o c a t i o n */
  557.  
  558. TokNode *
  559. #ifdef __STDC__
  560. newTokNode( void )
  561. #else
  562. newTokNode( )
  563. #endif
  564. {
  565.     static TokNode *FreeList = NULL;
  566.     TokNode *p, *newblk;
  567.  
  568.     if ( FreeList == NULL )
  569.     {
  570.         newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode));
  571.         if ( newblk == NULL )
  572.             fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
  573.         for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++)
  574.         {
  575.             p->next = (Node *)FreeList;    /* add all new token nodes to FreeList */
  576.             FreeList = p;
  577.         }
  578.     }
  579.     p = FreeList;
  580.     FreeList = (TokNode *)FreeList->next;/* remove a Junction node */
  581.     p->next = NULL;                        /* NULL the ptr we used */
  582.  
  583.     p->ntype = nToken;
  584.     p->rname = CurRule;
  585.     p->file = CurFile;
  586.     p->line = zzline;
  587.     p->altstart = NULL;
  588.  
  589.     return p;
  590. }
  591.  
  592. RuleRefNode *
  593. #ifdef __STDC__
  594. newRNode( void )
  595. #else
  596. newRNode( )
  597. #endif
  598. {
  599.     static RuleRefNode *FreeList = NULL;
  600.     RuleRefNode *p, *newblk;
  601.  
  602.     if ( FreeList == NULL )
  603.     {
  604.         newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode));
  605.         if ( newblk == NULL )
  606.             fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
  607.         for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++)
  608.         {
  609.             p->next = (Node *)FreeList;    /* add all new rref nodes to FreeList */
  610.             FreeList = p;
  611.         }
  612.     }
  613.     p = FreeList;
  614.     FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */
  615.     p->next = NULL;                        /* NULL the ptr we used */
  616.  
  617.     p->ntype = nRuleRef;
  618.     p->rname = CurRule;
  619.     p->file = CurFile;
  620.     p->line = zzline;
  621.     p->astnode = ASTinclude;
  622.     p->altstart = NULL;
  623.     
  624.     return p;
  625. }
  626.  
  627. Junction *
  628. #ifdef __STDC__
  629. newJunction( void )
  630. #else
  631. newJunction( )
  632. #endif
  633. {
  634.     static Junction *FreeList = NULL;
  635.     Junction *p, *newblk;
  636.  
  637.     if ( FreeList == NULL )
  638.     {
  639.         newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction));
  640.         if ( newblk == NULL )
  641.             fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
  642.         for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++)
  643.         {
  644.             p->p1 = (Node *)FreeList;    /* add all new Junction nodes to FreeList */
  645.             FreeList = p;
  646.         }
  647.     }
  648.     p = FreeList;
  649.     FreeList = (Junction *)FreeList->p1;/* remove a Junction node */
  650.     p->p1 = NULL;                        /* NULL the ptr we used */
  651.  
  652.     p->ntype = nJunction;    p->visited = 0;
  653.     p->jtype = Generic;
  654.     p->rname = CurRule;
  655.     p->file = CurFile;
  656.     p->line = zzline;
  657.     p->exception_label = NULL;
  658.     p->fset = (set *) calloc(CLL_k+1, sizeof(set));
  659.     require(p->fset!=NULL, "cannot allocate fset in newJunction");
  660.  
  661.     return p;
  662. }
  663.  
  664. ActionNode *
  665. #ifdef __STDC__
  666. newActionNode( void )
  667. #else
  668. newActionNode( )
  669. #endif
  670. {
  671.     static ActionNode *FreeList = NULL;
  672.     ActionNode *p, *newblk;
  673.  
  674.     if ( FreeList == NULL )
  675.     {
  676.         newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode));
  677.         if ( newblk == NULL )
  678.             fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
  679.         for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++)
  680.         {
  681.             p->next = (Node *)FreeList;    /* add all new Action nodes to FreeList */
  682.             FreeList = p;
  683.         }
  684.     }
  685.     p = FreeList;
  686.     FreeList = (ActionNode *)FreeList->next;/* remove a Junction node */
  687.     p->next = NULL;                        /* NULL the ptr we used */
  688.     
  689.     p->ntype = nAction;
  690.     return p;
  691. }
  692.  
  693. /*
  694.  * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion.
  695.  * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs.
  696.  * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes.
  697.  *
  698.  * if ( lock[k]==TRUE ) then we have been here before looking for k tokens
  699.  * of lookahead.
  700.  */
  701. char *
  702. #ifdef __STDC__
  703. makelocks( void )
  704. #else
  705. makelocks( )
  706. #endif
  707. {
  708.     char *p = (char *) calloc(CLL_k+1, sizeof(char));
  709.     require(p!=NULL, "cannot allocate lock array");
  710.     
  711.     return p;
  712. }
  713.